package pl.jtb.ctl.tabory.ui.boe.ui.ce;

import java.util.List;

import org.apache.log4j.Logger;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;

import pl.jtb.ctl.tabory.dao.api.services.ICompositionService;
import pl.jtb.ctl.tabory.dao.data.vo.CompositionVO;
import pl.jtb.ctl.tabory.dao.impl.mybatis.servicemanager.ServiceManager;
import pl.jtb.ctl.tabory.ui.boe.osgi.Activator;
import pl.jtb.ctl.tabory.ui.boe.selection.CompositionSelection;
import pl.jtb.ctl.tabory.ui.editors.AbstractMasterSectionPart;
import pl.jtb.ctl.tabory.ui.editors.EditorStateSL;
import pl.jtb.ctl.tabory.ui.osgi.UiBundleActivator;
import pl.jtb.ctl.tabory.ui.selection.ISelectionListener;

public class CompositionMasterSectionPart extends AbstractMasterSectionPart<CompositionSelection> {

    private final static Logger logger = Logger.getLogger(CompositionMasterSectionPart.class);

    private boolean isToolBarVisible;
    private boolean isFilterVisible;

    private ISelectionListener<CompositionSelection> selectionListener;

    private Section filterSection;
    private Text filterCompositionName;
    private CompositionNameFilter compositionNameFilter;

    public CompositionMasterSectionPart(Composite parent, FormToolkit toolkit, int style, String sectionName, boolean isToolBarVisible, boolean isFilterVisible) {
        super(parent, toolkit, style, sectionName);
        this.isFilterVisible = isFilterVisible;
        this.isToolBarVisible = isToolBarVisible;
        initGui(parentSection, toolkit);
        postInitGui(parentSection, toolkit);
        initActions();
    }

    @Override
    public CompositionSelection getSelection() {
        logger.debug("Retriving selection: " + selection);
        return this.selection;
    }

    @Override
    public void setSelection(CompositionSelection selection) {
        logger.debug("Setting selection: " + selection);
        this.selection = selection;
        refreshToolBar();
        if (selection.getEditorState().equals(EditorStateSL.CLEAN)) {
            setEnabled(true);
        } else {
            setEnabled(false);
        }
        tableViewer.setInput(selection.getListAllCompositions());

    }

    @Override
    public void addSelectionListener(ISelectionListener<CompositionSelection> listner) {
        this.selectionListener = listner;

    }

    @Override
    public void removeSelectionListener(ISelectionListener<CompositionSelection> listner) {
    }

    @Override
    protected void initGui(Section parentSection, FormToolkit toolkit) {
        toolBar = getToolBar(parentSection, toolkit);
        parentSection.setTextClient(toolBar);
        toolBar.setVisible(isToolBarVisible);

        Composite container = toolkit.createComposite(parentSection);
        GridLayoutFactory.fillDefaults().numColumns(1).applyTo(container);
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(container);
        parentSection.setClient(container);

        tableViewer = new TableViewer(container, SWT.BORDER | SWT.FULL_SELECTION);
        table = tableViewer.getTable();
        table.setHeaderVisible(true);

        TableColumn columnUserName = new TableViewerColumn(tableViewer, SWT.NONE).getColumn();
        columnUserName.setWidth(120);
        columnUserName.setText(Activator.getMessage("compositions.editor.master.table.col0"));

        tableViewer.setLabelProvider(new TableLabelProvider());
        tableViewer.setContentProvider(new TableContentProvider());
        tableViewer.setSorter(new TableViewerSorter());
        tableViewer.addFilter(compositionNameFilter = new CompositionNameFilter());

        toolkit.paintBordersFor(table);
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(table);

        filterSection = toolkit.createSection(container, Section.TWISTIE | Section.TITLE_BAR);
        GridLayoutFactory.fillDefaults().numColumns(1).margins(5, 5).applyTo(filterSection);
        toolkit.paintBordersFor(filterSection);
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(false, false).applyTo(filterSection);

        Composite filterComposite = toolkit.createComposite(filterSection);
        filterSection.setText(UiBundleActivator.getMessage("common.filter"));
        toolkit.paintBordersFor(filterComposite);
        filterSection.setClient(filterComposite);
        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(filterComposite);
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(false, false).applyTo(filterComposite);

        Label filterUserNameLabel = toolkit.createLabel(filterComposite, Activator.getMessage("compositions.master.label.name"));
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, true).applyTo(filterUserNameLabel);
        filterCompositionName = toolkit.createText(filterComposite, null);
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).hint(100, SWT.DEFAULT).grab(true, true).applyTo(filterCompositionName);

        toolkit.adapt(filterComposite, true, true);
        filterSection.setVisible(isFilterVisible);

    }

    @Override
    protected void postInitGui(Section parentSection, FormToolkit toolkit) {
    }

    @Override
    protected void initActions() {
        filterCompositionName.addKeyListener(new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e) {
                compositionNameFilter.setPattern(filterCompositionName.getText());
                tableViewer.refresh();
            }
        });
        tableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
            @Override
            public void selectionChanged(SelectionChangedEvent event) {
                logger.debug("Table selection changed");
                IStructuredSelection tableSelection = (IStructuredSelection) event.getSelection();
                CompositionVO selectedComposition = (CompositionVO) tableSelection.getFirstElement();
                selection.setSelectedComposition(selectedComposition);
                selectionListener.selectionChanged(selection);
            }
        });
        toolItemNew.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                selection.setEditorState(EditorStateSL.NEW);
                selection.setSelectedComposition(null);
                selectionListener.selectionChanged(selection);
            }
        });
        toolItemEdit.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                selection.setEditorState(EditorStateSL.EDITING);
                selectionListener.selectionChanged(selection);
            }
        });
        toolItemDelete.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                try {
                    ICompositionService compositionService = ServiceManager.getInstance().getCompositionService();
                    CompositionVO selectedComposition = selection.getSelectedComposition();
                    boolean openConfirm = MessageDialog.openConfirm(getSection().getShell(), Activator.getMessage("composition.editor.questions.delete.title"), Activator.getMessage("composition.editor.questions.delete.message"));
                    if (openConfirm) {
                        compositionService.deleteComposition(selectedComposition);
                        selection.setListAllCompositions(compositionService.getListAllCompositions());
                        selectionListener.selectionChanged(selection);
                    }
                } catch (Exception ex) {
                    logger.error(ex.getMessage(), ex);
                }
            }
        });

    }

    @Override
    protected void setEnabled(boolean isEnabled) {
        super.setEnabled(isEnabled);
        filterSection.setEnabled(isEnabled);
    }

    protected void refreshToolBar() {
        if (selection.getSelectedComposition() == null) {
            toolItemNew.setEnabled(true);
            toolItemEdit.setEnabled(false);
            toolItemDelete.setEnabled(false);
        } else {
            toolItemNew.setEnabled(true);
            toolItemEdit.setEnabled(true);
            toolItemDelete.setEnabled(true);
        }
    }

    private static class TableLabelProvider extends LabelProvider implements ITableLabelProvider {

        public Image getColumnImage(Object element, int columnIndex) {
            return null;
        }

        public String getColumnText(Object element, int columnIndex) {
            CompositionVO composition = (CompositionVO) element;
            switch (columnIndex) {
                case 0:
                    return composition.getInternalId();
                default:
                    return composition.toString();
            }
        }
    }

    private static class TableContentProvider implements IStructuredContentProvider {

        @SuppressWarnings("unchecked")
        public Object[] getElements(Object inputElement) {
            List<CompositionVO> list = (List<CompositionVO>) inputElement;
            return list.toArray();
        }

        public void dispose() {
        }

        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
        }
    }

    private static class TableViewerSorter extends ViewerSorter {
        @Override
        public int compare(Viewer viewer, Object e1, Object e2) {
            CompositionVO v1 = (CompositionVO) e1;
            CompositionVO v2 = (CompositionVO) e2;
            return super.compare(viewer, v1.getInternalId(), v2.getInternalId());
        }
    }

    private static class CompositionNameFilter extends ViewerFilter {

        private String patter;

        public void setPattern(final String pattern) {
            this.patter = pattern;
        }

        @Override
        public boolean select(Viewer viewer, Object parentElement, Object element) {
            if (patter == null || patter.length() == 0) {
                return true;
            }
            CompositionVO composition = (CompositionVO) element;
            if (composition.getInternalId().contains(patter)) {
                return true;
            }
            return false;
        }

    }

}
